﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

using Cronus.View.Data;

namespace Cronus.Windows
{
    /// <summary>
    /// Kind of a hack for a class.  All that happens is a collection is created from the possible
    /// tasks associated with the dataset.  Really want to be able to get access to this in XAML
    /// from the EditEvents class.
    /// </summary>
    public class TasksToDisplay : ObservableCollection<CronusData.TasksRow>
    {
        public TasksToDisplay() : base(EditEvents.AllTasksToSelectFrom)
        {
        }
    }

    /// <summary>
    /// Interaction logic for EditEvents.xaml
    /// </summary>
    public partial class EditEvents : Window
    {
        //*** Constants ***//
        //*** Static ***//
        //*** Member Variables ***//
        private DateTime _CurrentDate;

        //*** Properties ***//
        public static ObservableCollection<CronusData.TasksRow> AllTasksToSelectFrom
        {
            get
            {
                return GetAllTasksToSelectFrom();
            }
        }

        public static ObservableCollection<CronusData.TasksRow> GetAllTasksToSelectFrom()
        {
            return CronusDataSet.Tasks.ViewByTaskName;
        }

        public static CronusData CronusDataSet { get; set; }

        //*** Constructors ***//
        public EditEvents()
        {
            InitializeComponent();

            // Give the user an initial date of today.
            _CurrentDate = DateTime.Now;
            _DateTextBox.Text = _CurrentDate.ToShortDateString();

            // By default, the ListView doesn't select anything, so
            // disable the Delete Event button.
            _DeleteEventBtn.IsEnabled = false;

            // Nothing is entered in the add event dialog, can't be
            // ready to add an event.
            _AddEventBtn.IsEnabled = false;

            InitializeScreenBasedOnDataSet();
        }

        //*** Methods ***//
        /// <summary>
        /// This method is called when the date is changed and the ListView
        /// needs to be udpated.
        /// </summary>
        private void OnDateChange()
        {
            // Local variables
            DataRow[] allEvents = null;
            allEvents = CronusDataSet.AllEvents.GetAllEventsFromDate(_CurrentDate);

            SummaryBase aTotalSummary = CronusDataSet.GetTotalSummary();
            aTotalSummary.StartDate = _CurrentDate;

            double dTotalHours = aTotalSummary.GetHoursToday();
            _TotalEventsTime.Text = "Total Time: " + TaskSummary.FormatHoursAsString(dTotalHours);

            if (null != allEvents)
            {
                _EventListView.ItemsSource = allEvents;
            }
        }

        /// <summary>
        /// This function is called when the the CronosDataSet property
        /// is updated.
        /// </summary>
        private void InitializeScreenBasedOnDataSet()
        {
            if ((null != CronusDataSet) && (null != _TaskListCombo))
            {
                // Bind the task combo box to the task list.
                //_TaskListCombo.ItemsSource = _CronusData.Tasks.ViewByTaskName;
                //if (0 < _CronusData.Tasks.Count)
                //{
                //    _TaskListCombo.SelectedIndex = 0;
                //}

                // Update the list of events being displayed.
                OnDateChange();
            }
        }

        /// <summary>
        /// This is a callback for when the user leaves the text box when
        /// entering a date.
        /// </summary>
        /// <param name="sender">Not used.</param>
        /// <param name="anArg">Not used.</param>
        private void DateTextBox_LostFocus(object sender, RoutedEventArgs anArg)
        {
            ParseUserEnteredDate();
        }

        /// <summary>
        /// This function will validate the user input of the date and call
        /// to update the list of events being viewed.
        /// </summary>
        private void ParseUserEnteredDate()
        {
            // Local variables
            string strDateText = _DateTextBox.Text;

            try
            {
                if ((null != strDateText) && (0 < strDateText.Length))
                {
                    _CurrentDate = DateTime.Parse(strDateText);
                    OnDateChange();
                }
            }
            catch (Exception)
            {
                MessageBox.Show("The entered date, " + strDateText + ", is invalid.");
                _DateTextBox.Text = _CurrentDate.ToShortDateString();
            }
        }

        /// <summary>
        /// This is a callback and is going to check for the return key
        /// being pressed.  If the return key was pressed, the TextBox will
        /// act as if the user had left it.
        /// </summary>
        /// <param name="sender">Not used.</param>
        /// <param name="e">Used to determine which key was pressed.</param>
        private void DateTextBox_KeyDown(object sender, KeyEventArgs e)
        {
            if (Key.Return == e.Key)
            {
                ParseUserEnteredDate();
            }
        }

        /// <summary>
        /// When the TextBox looses focus, refresh the data so that the
        /// changes are immediately visible.
        /// </summary>
        /// <param name="sender">Not used.</param>
        /// <param name="e">Not used.</param>
        private void GridColumn_LostFocus(object sender, RoutedEventArgs e)
        {
            _EventListView.Items.Refresh();
        }

        /// <summary>
        /// When the user presses a key, check to see if the key press
        /// was one to refresh the data so their changes are immediately
        /// visible (i.e. press of the return key, etc...).
        /// </summary>
        /// <param name="sender">Not used.</param>
        /// <param name="e">Not used.</param>
        private void GridColumn_KeyDown(object sender, KeyEventArgs e)
        {
            // Only check for the return key, the tab key is covered by
            // the loss of focus event.
            if (Key.Return == e.Key)
            {
                _EventListView.Items.Refresh();
            }
        }

        /// <summary>
        /// The function deletes the currently selected event from the
        /// display and refreshes the grid.
        /// </summary>
        /// <param name="sender">Not used.</param>
        /// <param name="e">Not used.</param>
        private void DeleteEventBtn_Click(object sender, RoutedEventArgs e)
        {
            // Local variables
            CronusData.AllEventsRow anEvent = null;

            // Find the selected event.
            anEvent = _EventListView.SelectedItem as CronusData.AllEventsRow;
            if (null != anEvent)
            {
                // Delete the event, but also refresh the events (need to do
                // a full refresh of the data, otherwise we'll end up with
                // empty rows and exceptions being thrown, just pretend the
                // date changed, this will cause a new query on the table).
                CronusDataSet.DeleteEvent(anEvent);
                OnDateChange();
            }
        }

        /// <summary>
        /// This callback will determine if anything has been selected by the
        /// user.  If the user has selected something, the delete event button
        /// becomes active, otherwise it stays disabled.
        /// </summary>
        /// <param name="sender">Not used.</param>
        /// <param name="e">Contains the list of items selected.</param>
        private void EventListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            // Local variables
            bool bIsDone = true;
            CronusData.AllEventsRow aRow = null;

            // Check to see if the current row is done or not.
            aRow = _EventListView.SelectedItem as CronusData.AllEventsRow;
            if (null != aRow)
            {
                bIsDone = aRow.IsEventDone;
            }

            // Only if the user has selected something and the event is not
            // timing should we allow the user to delete events.
            if ((0 < e.AddedItems.Count) && (bIsDone))
            {
                _DeleteEventBtn.IsEnabled = true;
            }
            else
            {
                _DeleteEventBtn.IsEnabled = false;
            }
        }

        /// <summary>
        /// This validates the text in both the StartTime and EndTime boxes.
        /// If valid times, the "Add Event" button becomes active, if not,
        /// the button is disabled.
        /// </summary>
        /// <param name="sender">Used to determine the updated TextBox.</param>
        /// <param name="e">Not used.</param>
        private void AddTimeTextBox_LostFocus(object sender, RoutedEventArgs e)
        {
            // Local variables
            TextBox aTextBox = sender as TextBox;
            DateTime? aStartTime = null;
            DateTime? anEndTime = null;

            if (null != aTextBox)
            {
                if (_StartTimeTextBox == sender)
                {
                    aStartTime = GetTimeFromTextBox(_StartTimeTextBox, true);
                    anEndTime = GetTimeFromTextBox(_EndTimeTextBox, false);
                }
                else
                {
                    aStartTime = GetTimeFromTextBox(_StartTimeTextBox, false);
                    anEndTime = GetTimeFromTextBox(_EndTimeTextBox, true);
                }

                // Check to make sure both time objects were parsed, assume
                // failure first.
                _AddEventBtn.IsEnabled = false;
                if ((null != aStartTime) && (null != anEndTime))
                {
                    // Check to make sure that the end time is later than the
                    // start time.
                    if (aStartTime < anEndTime)
                    {
                        _AddEventBtn.IsEnabled = true;
                    }
                }
            }
        }

        /// <summary>
        /// This function will return the time entered in the TextBox.  If the
        /// time is invalid, NULL will be returned.
        /// </summary>
        /// <param name="bShowMessage">TRUE will show the error message.</param>
        /// <returns>The time if successfully parsed, NULL otherwise.</returns>
        private DateTime? GetTimeFromTextBox(TextBox aTextBox, bool bShowMessage)
        {
            DateTime? aTime = null;
            try
            {
                if ((null != aTextBox.Text) && (0 < aTextBox.Text.Length))
                {
                    aTime = DateTime.Parse(aTextBox.Text);
                }
            }
            catch (Exception)
            {
                if (bShowMessage)
                {
                    MessageBox.Show("The time, \"" + aTextBox.Text + "\", is an invalid time.", Cronus.View.Properties.Resources.Title);
                }
            }
            return aTime;
        }

        /// <summary>
        /// This function will add the event defined by 
        /// </summary>
        /// <param name="sender">Not used.</param>
        /// <param name="e">Not used.</param>
        private void AddEventBtn_Click(object sender, RoutedEventArgs e)
        {
            // Local variables
            //DataRowView aRowView = null;
            CronusData.TasksRow aTask = null;
            DateTime? aStartTime = GetTimeFromTextBox(_StartTimeTextBox, false);
            DateTime? anEndTime = GetTimeFromTextBox(_EndTimeTextBox, false);

            if ((null != aStartTime) && (null != anEndTime))
            {
                // Create new DateTime objects with the correct date and time.
                DateTime aNewStart = new DateTime(_CurrentDate.Year,
                                                  _CurrentDate.Month,
                                                  _CurrentDate.Day,
                                                  aStartTime.Value.Hour,
                                                  aStartTime.Value.Minute,
                                                  aStartTime.Value.Second);
                DateTime aNewEnd = new DateTime(_CurrentDate.Year,
                                                _CurrentDate.Month,
                                                _CurrentDate.Day,
                                                anEndTime.Value.Hour,
                                                anEndTime.Value.Minute,
                                                anEndTime.Value.Second);

                // Get the selected task.
                aTask = _TaskListCombo.SelectedItem as CronusData.TasksRow;
                if (null != aTask)
                {
                    if (CronusDataSet.AddEvent(aNewStart, aNewEnd, aTask.Name))
                    {
                        // Successful, update the display and then clear
                        // the input boxes.
                        OnDateChange();
                        _StartTimeTextBox.Text = String.Empty;
                        _EndTimeTextBox.Text = String.Empty;
                        _AddEventBtn.IsEnabled = false;
                    }
                }
            }
        }
    }
}
